package hk.edu.cityu.is.riskmgmt.agent;

import hk.edu.cityu.is.riskmgmt.algorithm.interbank.BankNetworkClearing;
import hk.edu.cityu.is.riskmgmt.data.SharedData;
import hk.edu.cityu.is.riskmgmt.interfaces.Agent;

import org.apache.log4j.Logger;

/**
 * @author chaolu
 * 
 */
public class FinancialMarketParticipant implements Agent {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(FinancialMarketParticipant.class);

	public FinancialMarketParticipant() {
		super();
		// TODO Auto-generated constructor stub
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * hk.edu.cityu.is.riskmgmt.interfaces.Agent#step(hk.edu.cityu.is.riskmgmt
	 * .data.SharedData)
	 */
	@Override
	public SharedData step(SharedData sd) {
		// TODO Auto-generated method stub
		// clear
		int bankNO = sd.getBankno();
		if (logger.isInfoEnabled()) {
			logger.info("step(SharedData) - Numbers of Bank: " + bankNO); //$NON-NLS-1$
		}
		int tick = sd.getTick();
		if (logger.isInfoEnabled()) {
			logger.info("step(SharedData) - Tick: " + tick); //$NON-NLS-1$
		}

		double[] cashReserve = sd.getCapital_reserve();
		double[] security = sd.getTrading_assets();
		double[][] inter = sd.getInterbank_payment();
		// The following three arrays are used to store the results after the
		// clearing process
		double[] P_star = new double[bankNO];
		String[] defaultSequence = new String[bankNO];
		String[] nonDefaultBanks = new String[bankNO];
		double[] leftAsset = new double[bankNO];
		String[] bankID = { "Bank01", "Bank02", "Bank03" };
		double[] leftCash = new double[bankNO];
		double[] leftSecurity = new double[bankNO];
		BankNetworkClearing b = new BankNetworkClearing();
		if (logger.isInfoEnabled()) {
			logger.info("step(SharedData) - Start clearing"); //$NON-NLS-1$
		}
		int a = b.doClearing(bankNO, bankID, cashReserve, security, inter,
				P_star, defaultSequence, nonDefaultBanks, leftAsset, leftCash,
				leftSecurity);

		if (logger.isInfoEnabled()) {
			logger.info("step(SharedData) - FMP: Total number of default banks is: " + a); //$NON-NLS-1$
		}

		if (logger.isInfoEnabled()) {
			logger.info("step(SharedData) - FMP: The clearing vector is: "); //$NON-NLS-1$
		}
		for (int i = 0; i < bankNO; i++) {
			if (logger.isInfoEnabled()) {
				logger.info("step(SharedData) - FMP: " + P_star[i] + " "); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}

		if (logger.isInfoEnabled()) {
			logger.info("step(SharedData) - FMP: The left asset vector after clearing is: "); //$NON-NLS-1$
		}
		for (int i = 0; i < bankNO; i++) {
			if (logger.isInfoEnabled()) {
				logger.info("step(SharedData) - FMP: A:" + leftAsset[i] + " S" + leftSecurity[i] + " C" + leftCash[i]); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
		}
		if (logger.isInfoEnabled()) {
			logger.info("step(SharedData) - FMP: The defaulting sequence is "); //$NON-NLS-1$
		}
		for (int i = 0; i < a; i++) {
			if (logger.isInfoEnabled()) {
				logger.info("step(SharedData) - FMP: " + defaultSequence[i] + " "); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
		for (int i = 0; i < bankNO; i++) {
			if (logger.isInfoEnabled()) {
				logger.info("step(SharedData) - " + sd.getOneBankTradingAssets(i) + P_star[i] + sd.getOneBankCapitalReserve(i)); //$NON-NLS-1$
			}
			sd.setOneBankPaymentVector(i, sd.getOneBankTradingAssets(i)
					+ P_star[i] + sd.getOneBankCapitalReserve(i));
		}

		// interbank payment

		if (logger.isInfoEnabled()) {
			logger.info("step(SharedData) - FMP: Start interbank payment at tick " + tick); //$NON-NLS-1$
		}
		double[][] payment = sd.getInterbank_payment();
		// the first bankNO-1 columns are interbank payment between bank 1 and
		// other banks,
		// then bankNO-2 columns are interbank payment between bank 2 and other
		// banks,
		// ....
		// and so on, the last one is the interbank payment between bankNO-1 and
		// BankNO
		// the following algorithm wlll carry out the interbank payment
		// mentioned
		// above.

		int banknumber = bankNO;
		int bankno = banknumber - 1;
		int start = 0;
		int counter = 1;
		int columnNO = 0;
		while (bankno > 0) {

			for (int i = counter + 1; i <= banknumber; i++) {
				if (logger.isInfoEnabled()) {
					logger.info("step(SharedData) - " + counter + "-" + i); //$NON-NLS-1$ //$NON-NLS-2$
				}
				if (payment[columnNO][tick] > 0) {
					if (sd.getOneBankCash(counter) > 0) {
						// have cash to repay
						double net_payment = Math.abs(payment[columnNO][tick]);
						sd.setOneBankCash(counter - 1,
								sd.getOneBankCash(counter - 1) - net_payment);
						sd.setOneBankCash(i - 1, sd.getOneBankCash(i - 1)
								+ net_payment);
						logger.info("step(SharedData) - " + "Amount: " + net_payment); //$NON-NLS-1$ //$NON-NLS-2$
						sd.setOneBankIsDefault(0, false);

					} else {
						sd.setOneBankIsDefault(0, true);
						logger.info("step(SharedData) - "
								+ "The interbank payment causes default.");
					}
				}

			}
			bankno--;
			counter++;
			columnNO++;
		}
		return sd;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
